# Import the base Model class from Flask-AppBuilder.
from flask_appbuilder import Model
# Import column types and relationship-defining constructs from SQLAlchemy.
from sqlalchemy import Column, ForeignKey, Integer, String, Text
# Import the relationship function to define relationships between models.
from sqlalchemy.orm import relationship

# Import custom base models and mixins from the application.
from myapp.models.base import MyappModelBase
from myapp.models.helpers import AuditMixinNullable

# Import the Project model to establish a foreign key relationship.
from .model_team import Project


# Get the metadata from the base Flask-AppBuilder Model.
# This metadata object holds the schema information.
metadata = Model.metadata


# Define the Training_Model class, which maps to the 'model' table in the database.
# It inherits from Flask-AppBuilder's Model, our custom AuditMixin, and a base model.
class Training_Model(Model, AuditMixinNullable, MyappModelBase):
    # Specify the table name in the database.
    __tablename__ = 'model'
    # Define the primary key column for the table.
    id = Column(Integer, primary_key=True)
    # Define the name of the model. This column cannot be null.
    name = Column(String(100), nullable=False)
    # Define the version of the model.
    version = Column(String(100))
    # A description of the model.
    describe = Column(String(1000))
    # The storage path of the model files.
    path = Column(String(200))
    # A direct download URL for the model.
    download_url = Column(String(200))
    # Define the foreign key relationship to the 'project' table.
    project_id = Column(Integer, ForeignKey('project.id'))
    # Establish the ORM relationship to the Project model.
    project = relationship(Project, foreign_keys=[project_id])
    # The ID of the pipeline that trained this model.
    pipeline_id = Column(Integer, default=0)
    # The specific run ID of the training pipeline instance.
    run_id = Column(
        String(100), nullable=False, default='0'
    )  # pipeline run instance, 0为非训练任务
    # The runtime duration of the training job.
    run_time = Column(String(100))
    # The machine learning framework used (e.g., TensorFlow, PyTorch).
    framework = Column(String(100))
    # A JSON string to store performance metrics of the model.
    metrics = Column(Text, default='{}')
    # The MD5 checksum of the model file for integrity checks.
    md5 = Column(String(200), default='')
    # The type of API exposed by the model (e.g., REST, gRPC).
    api_type = Column(String(100))

    # The type of the model, represented as an integer (enum).
    type = Column(Integer, nullable=True, default=0)
    # The application scene or domain for the model, as an integer (enum).
    scene = Column(Integer, nullable=True, default=0)
    # The primary dimension or category of the model, as an integer (enum).
    dimension = Column(Integer, nullable=True, default=0)
    # A flag indicating if this is a pre-trained, public model.
    is_public = Column(Integer, nullable=True, default=2, comment='是否为预置模型，1-是，2-否')
    # A string of comma-separated labels for tagging the model.
    labels = Column(String(1000), nullable=True, comment='模型标签')
    # A JSON string containing the configuration used for training the model.
    train_config = Column(Text(65536), nullable=True, default='{}', comment='训练配置')
    # A sub-category or dimension for the model.
    sub_dimension = Column(String(100), nullable=True, comment='模型子类别')
    # The source of the model (e.g., uploaded, trained), as an integer (enum).
    source = Column(Integer, nullable=True, default=0, comment='模型来源')
    # A path or URL to the model's README file.
    readme = Column(String(1000), nullable=True, default='', comment='模型readme')
    # The geographical or logical region where the model is stored/managed.
    region = Column(String(100), nullable=False, default='default', server_default='default', comment='地区')

    # Define the string representation of the model object.
    def __repr__(self):
        # When an instance of Training_Model is printed, it will show its name.
        return self.name
